#ifdef QING_QUEUE_SRC

#include "RingQueue.h"
#include <iostream>
#include <stdlib.h>



#define DEFAULT_SIZE 16

template<typename T>
RingQueue<T>::RingQueue()
    : m_iCapacity(DEFAULT_SIZE)
    , m_iFront(0)
    , m_iRear(0)
    , m_pData(nullptr)
{
    m_pData = new (std::nothrow) T[m_iCapacity];
}

template<typename T>
RingQueue<T>::RingQueue(size_t iSize)
    : m_iCapacity(iSize)
    , m_iFront(0)
    , m_iRear(0)
    , m_pData(nullptr)
{
    m_pData = new (std::nothrow) T[m_iCapacity];
}

template<typename T>
RingQueue<T>::~RingQueue()
{
    m_iCapacity = m_iRear = m_iFront = 0;
    if (m_pData)
    {
        delete [] m_pData;
        m_pData = nullptr;
    }
}

template<typename T>
bool RingQueue<T>::isEmpty()
{
    return (m_iFront == m_iRear);
}

template<typename T>
bool RingQueue<T>::isFull()
{
    return m_iFront == (m_iRear + 1) % m_iCapacity;
}

template<typename T>
void RingQueue<T>::pushBack(const T& data)
{
    if (isFull())
    {
        resize(m_iCapacity * 2);
    }

    if (m_pData)
    {
        m_pData[m_iRear] = data;
        m_iRear = (m_iRear + 1) % m_iCapacity;
    }

    return;
}

template<typename T>
T RingQueue<T>::popFront()
{
    if (isEmpty() || !m_pData)
    {
        return T();
    }

    size_t iPreIndex = m_iFront;
    m_iFront = (m_iFront + 1) % m_iCapacity;
    return m_pData[iPreIndex];
}

template<typename T>
size_t RingQueue<T>::size() const
{
    return (m_iRear - m_iFront + m_iCapacity) % m_iCapacity;
}

template<typename T>
void RingQueue<T>::resize(size_t iSize)
{
    T* pTmp = new (std::nothrow) T[iSize];
    if (pTmp)
    {
        size_t iIndex = 0;
        for (size_t i = m_iFront; i != m_iRear; i = (i + 1) % m_iCapacity)
        {
            pTmp[iIndex++] = m_pData[i];
        }

        if (m_pData)
        {
            delete [] m_pData;
            m_pData = nullptr;
        }

        m_iFront = 0;
        m_iRear = iIndex;
        m_iCapacity = iSize;
        m_pData = pTmp;
    }

    return;
}

template<typename T>
size_t RingQueue<T>::capacity() const
{
    return m_iCapacity;
}

//template class RingQueue<int>;
//template class RingQueue<double>;

#endif
